import 'dart:async';
import 'dart:io';

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart';
import 'package:player_plugin/polyv_controller.dart';
import 'package:player_plugin/video_control_bar_style.dart';
import 'package:player_plugin/video_definition.dart';
import 'package:player_plugin/video_play_options.dart';
import 'package:player_plugin/video_player_value.dart';
import 'package:player_plugin/video_speed.dart';
import 'package:player_plugin/video_style.dart';
import 'package:player_plugin/widget/brightness.dart';
import 'package:player_plugin/widget/linear_progress_bar.dart';
import 'package:player_plugin/widget/video_bottom_bar.dart';
import 'package:player_plugin/widget/video_definition_side_bar.dart';
import 'package:player_plugin/widget/video_estimated_time_bar.dart';
import 'package:player_plugin/widget/video_loading_view.dart';
import 'package:player_plugin/widget/video_retry_button.dart';
import 'package:player_plugin/widget/video_speed_bar.dart';
import 'package:player_plugin/widget/video_speed_tip.dart';
import 'package:player_plugin/widget/video_top_bar.dart';
import 'package:player_plugin/widget/volume.dart';
import 'package:sensors_plus/sensors_plus.dart';
import 'package:wakelock/wakelock.dart';

enum DataSourceType {
  /// 保利威视频ID
  videoVid,

  /// 视频播放地址
  videoUrl,

  /// 视频本地播放路径
  videoPath,
}

// 视频播放器，基于原生保利威点播 sdk 封装。通过 PlatformView 渲染视频。
class PolyvPlayer extends StatefulWidget {
  /// 视频资源
  final String dataSource;
  final DataSourceType sourceType;

  /// 播放器自定义属性
  final VideoPlayOptions? playOptions;
  final VideoStyle? videoStyle;
  final List<Widget>? children;
  final Widget? brightnessWidget;
  final Widget? volumeWidget;

  /// 初始化完成回调事件
  final ValueChanged<PolyvController>? onInit;

  /// 播放开始回调
  final ValueChanged<VideoPlayerValue>? onPlay;

  /// 播放开始回调
  final ValueChanged<VideoPlayerValue>? onTimeUpdate;

  /// 播放暂停回调
  final ValueChanged<VideoPlayerValue>? onPause;

  /// 播放结束回调
  final ValueChanged<VideoPlayerValue>? onEnded;

  /// 播放声音大小回调
  final ValueChanged<double>? onVolume;

  /// 屏幕亮度回调
  final ValueChanged<double>? onBrightness;

  /// 屏幕亮度回调
  final ValueChanged<bool>? onFullscreen;

  /// 顶部控制栏点击返回回调
  final ValueChanged<VideoPlayerValue>? onPop;

  /// 进度被拖拽的回调
  final VideoProgressDragHandle? onProgressDrag;

  /// 倍速改变的回调
  final ValueChanged<VideoSpeedItem>? onSpeedChange;

  /// 清晰度改变回调
  final ValueChanged<VideoDefinitionItem>? onDefinitionChange;

  //进入app时全屏、初始化铆点需要实现
  PolyvPlayer({
    Key? key,
    required this.dataSource,
    required this.sourceType,
    VideoPlayOptions? playOptions,
    VideoStyle? videoStyle,
    this.children,
    this.brightnessWidget,
    this.volumeWidget,
    this.onInit,
    this.onPlay,
    this.onTimeUpdate,
    this.onPause,
    this.onEnded,
    this.onVolume,
    this.onBrightness,
    this.onFullscreen,
    this.onPop,
    this.onProgressDrag,
    this.onSpeedChange,
    this.onDefinitionChange,
  })  : playOptions = playOptions ?? VideoPlayOptions(),
        videoStyle = videoStyle ?? VideoStyle(),
        super(key: key);

  @override
  State<StatefulWidget> createState() => VideoPlayerState();

  static VideoPlayerState of(BuildContext context) {
    final VideoPlayerState? result =
        context.findAncestorStateOfType<VideoPlayerState>();
    if (result != null) {
      return result;
    }
    throw Exception('未找到 JLVideoPlayerState');
  }
}

class VideoPlayerState extends State<PolyvPlayer>
    with SingleTickerProviderStateMixin, WidgetsBindingObserver {
  String get dataSource => widget.dataSource;

  DataSourceType get sourceType => widget.sourceType;

  VideoPlayOptions get playOptions => widget.playOptions!;

  VideoStyle get videoStyle => widget.videoStyle!;

  List<Widget>? get children => widget.children;

  Widget? get brightnessWidget => widget.brightnessWidget;

  Widget? get volumeWidget => widget.volumeWidget;

  ValueChanged<PolyvController>? get onInit => widget.onInit;

  ValueChanged<VideoPlayerValue>? get onPlay => widget.onPlay;

  ValueChanged<VideoPlayerValue>? get onTimeUpdate => widget.onTimeUpdate;

  ValueChanged<VideoPlayerValue>? get onPause => widget.onPause;

  ValueChanged<VideoPlayerValue>? get onEnded => widget.onEnded;

  ValueChanged<double>? get onVolume => widget.onVolume;

  ValueChanged<double>? get onBrightness => widget.onBrightness;

  ValueChanged<bool>? get onFullscreen => widget.onFullscreen;

  ValueChanged<VideoPlayerValue>? get onPop => widget.onPop;

  VideoProgressDragHandle? get onProgressDrag => widget.onProgressDrag;

  ValueChanged<VideoSpeedItem>? get onSpeedChange => widget.onSpeedChange;

  ValueChanged<VideoDefinitionItem>? get onDefinitionChange =>
      widget.onDefinitionChange;

  /// 控制器 - 快进 seekTo 暂停 pause 播放 play 摧毁 dispose
  late PolyvController _polyvController;
  late AnimationController _controlBarAnimationController;
  late Animation<double> _controlTopBarAnimation;
  late Animation<double> _controlBottomBarAnimation;

  /// 清晰度控制器
  AnimationController? _definitionBarController;

  /// 是否全屏
  bool _fullScreened = false;
  bool _initialized = false;

  /// 屏幕亮度
  final ValueNotifier<double> _brightness = ValueNotifier(0.0);
  double? _originBrightness;

  /// 视频音量
  final ValueNotifier<double> _volume = ValueNotifier(1.0);

  /// 预估滑动时间
  final EstimatedTimeNotifier _estimatedTimeNotifier = EstimatedTimeNotifier();

  /// 是否显示控制拦
  bool _showMenu = false;

  /// 是否正在缓冲
  bool _isBuffing = false;

  /// 是否结束
  bool _isEnded = false;
  Timer? _showTime;
  String _position = "--:--";
  String _duration = "--:--";

  /// 是否隐藏速度栏
  bool _hiddenSpeed = true;

  /// 是否隐藏速度tip
  bool _hiddenSpeedTip = true;

  /// 倍数按钮标题
  String _speedTitle = '';

  /// 倍数item
  VideoSpeedItem _speedItem = VideoSpeedItem();

  /// 清晰度按钮标题
  String _definitionTitle = '';

  /// 获取屏幕大小
  Size get screenSize => MediaQuery.of(context).size;

  /// 多播放器实例设置唯一key
  Key key = Key(DateTime.now().toString());

  late String _dataSource;
  late DataSourceType _sourceType;
  late int _viewID;
  late VideoControlBarStyle _videoControlBarStyle;
  int _selectedSpeedIndex = 0;
  StreamSubscription? _gyroscopeSubscription;
  bool _resumePlay = false;
  Duration _draggingDuration = Duration.zero;
  bool _hasPlayError = false;
  Duration _errorPosition = Duration.zero;

  @override
  void initState() {
    super.initState();

    _videoControlBarStyle = videoStyle.videoControlBarStyle.copyWith();

    /// 控制拦动画
    _controlBarAnimationController = AnimationController(
        duration: const Duration(milliseconds: 300), vsync: this);
    _controlTopBarAnimation = Tween(
            begin: -(videoStyle.videoTopBarStyle.height +
                videoStyle.videoTopBarStyle.margin.vertical * 2),
            end: 0.0)
        .animate(_controlBarAnimationController);
    _controlBottomBarAnimation = Tween(
            begin: -(_videoControlBarStyle.height +
                videoStyle.videoControlBarStyle.margin.vertical * 2),
            end: 0.0)
        .animate(_controlBarAnimationController);

    /// 常亮
    Wakelock.toggle(enable: true);

    /// 倍数按钮标题
    _speedTitle = videoStyle.videoSpeedButtonStyle.title;

    /// 清晰度按钮标题
    _definitionTitle = videoStyle.videoDefinitionButtonStyle.title;
    _resetDefinitionTitle();
    _initPlayer();
    WidgetsBinding.instance.addObserver(this);

    if (playOptions.autoRotate) {
      SystemChrome.setPreferredOrientations([]);
    }

    for (int i = 0; i < playOptions.speedList.length; i++) {
      VideoSpeedItem item = playOptions.speedList[i];
      if (item.speed == 1.0) {
        _selectedSpeedIndex = i;
        break;
      }
    }

    _gyroscopeSubscription = gyroscopeEventStream().listen((event) {
      if (event.x.abs() > 3.0 ||
          event.y.abs() > 3.0 ||
          event.z.abs() > 3.0 && playOptions.autoRotate) {
        SystemChrome.setPreferredOrientations([]);
      }
    });
  }

  /// 点击全屏或取消
  void toggleFullScreen() {
    if (_fullScreened) {
      SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
    } else {
      if (Platform.isIOS) {
        SystemChrome.setPreferredOrientations(
            [DeviceOrientation.landscapeRight]);
      } else {
        SystemChrome.setPreferredOrientations(
            [DeviceOrientation.landscapeLeft]);
      }
    }
  }

  Future<void> initBrightness() async {
    double brightness = await _polyvController.getBrightness();
    _brightness.value = brightness.toDouble();
    _originBrightness = brightness.toDouble();
  }

  @override
  void didUpdateWidget(PolyvPlayer oldWidget) {
    if (oldWidget.dataSource != dataSource ||
        oldWidget.sourceType != sourceType) {
      _resetDefinitionTitle();
      _updateDataSource(type: sourceType, source: dataSource);
    }
    super.didUpdateWidget(oldWidget);
  }

  @override
  void dispose() {
    _clearHideControlBarTimer();
    _polyvController.dispose();
    _controlBarAnimationController.dispose();
    Wakelock.toggle(enable: false);
    _brightness.dispose();
    _volume.dispose();
    _estimatedTimeNotifier.dispose();
    WidgetsBinding.instance.removeObserver(this);
    _gyroscopeSubscription?.cancel();

    ///恢复设备竖屏
    SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
    super.dispose();
  }

  @override
  void didChangeMetrics() {
    if (Platform.isAndroid) {
      WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
        changeScreenOrientation();
      });
    } else {
      changeScreenOrientation();
    }
  }

  void changeScreenOrientation() {
    if (!mounted) return;
    var orientation = MediaQuery.of(context).orientation;
    debugPrint('orientation: $orientation');
    bool fullscreen = false;
    if (orientation == Orientation.landscape) {
      //横屏
      fullscreen = true;
      SystemChrome.setEnabledSystemUIMode(
        SystemUiMode.manual,
        overlays: [],
      );
    } else if (orientation == Orientation.portrait) {
      fullscreen = false;
      SystemChrome.setEnabledSystemUIMode(
        SystemUiMode.manual,
        overlays: SystemUiOverlay.values,
      );
    }
    if (fullscreen != _fullScreened) {
      _fullScreened = fullscreen;
      _navigateLocally(context: context, fullScreen: fullscreen);
      //触发全屏事件
      onFullscreen?.call(fullscreen);
      changeControlBarAnimation();
      setState(() {});
    }
  }

  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    super.didChangeAppLifecycleState(state);
    switch (state) {
      case AppLifecycleState.inactive:
        debugPrint('inactive');
        bool isPlaying = _polyvController.value.isPlaying;
        if (isPlaying) {
          _resumePlay = true;
          _polyvController.pause();
        }
        break;
      case AppLifecycleState.paused:
        debugPrint('paused');
        break;
      case AppLifecycleState.resumed:
        debugPrint('resumed');
        if (_resumePlay) {
          _polyvController.play();
          _resumePlay = false;
        }
        break;
      case AppLifecycleState.detached:
        debugPrint('detached');
        break;
      case AppLifecycleState.hidden:
        debugPrint('hidden');
        break;
    }
  }

  void changeControlBarAnimation() {
    double paddingBottom = MediaQuery.of(context).viewPadding.bottom;
    if (paddingBottom == 0) {
      return;
    }
    if (_fullScreened) {
      _videoControlBarStyle = videoStyle.videoControlBarStyle.copyWith(
          height: videoStyle.videoControlBarStyle.height + paddingBottom);
    } else {
      _videoControlBarStyle = videoStyle.videoControlBarStyle.copyWith();
    }
    _controlBottomBarAnimation = Tween(
      begin: -(_videoControlBarStyle.height +
          videoStyle.videoControlBarStyle.margin.vertical * 2),
      end: 0.0,
    ).animate(_controlBarAnimationController);
  }

  void _updateDataSource({
    required DataSourceType type,
    required dynamic source,
    VoidCallback? initializeCallback,
  }) async {
    _initialized = false;
    _sourceType = type;
    _dataSource = source;
    PolyvController tempController = _createVideoPlayerController(
      type: type,
      source: source,
    );

    /// 释放老的 controller
    _polyvController.removeListener(_listener);
    _polyvController.dispose();

    /// 设置新的 controller 并开启监听和初始化
    _polyvController = tempController;
    _polyvController.addListener(_listener);
    _polyvController.initialize(viewID: _viewID).then((_) {
      _handleInit();
      initializeCallback?.call();
    });
    setState(() {});
  }

  void resetVideoPlayer() {
    setState(() {
      _isEnded = true;
      _position = _duration;
      _polyvController.value =
          const VideoPlayerValue(duration: Duration(seconds: 0));
    });
  }

  void _resetDefinitionTitle() {
    if (playOptions.definitionList.isNotEmpty) {
      for (VideoDefinitionItem item in playOptions.definitionList) {
        if (dataSource == item.dataSource) {
          _definitionTitle = item.title;
          break;
        }
      }
    }
  }

  void _listener() {
    if (!mounted) {
      return;
    }
    _polyvController.isBuffering().then((bool isBuffering) {
      _isBuffing = isBuffering;
    });
    if (_polyvController.value.isInitialized) {
      var oPosition = _polyvController.value.position;
      var oDuration = _polyvController.value.duration;

      widget.onTimeUpdate?.call(_polyvController.value);

      // debugPrint("error: " + controller.value.errorDescription);

      if (_polyvController.value.isPlaying) {
        setState(() {
          if (oDuration.inHours == 0) {
            var strPosition = oPosition.toString().split('.')[0];
            var strDuration = oDuration.toString().split('.')[0];
            _position =
                "${strPosition.split(':')[1]}:${strPosition.split(':')[2]}";
            _duration =
                "${strDuration.split(':')[1]}:${strDuration.split(':')[2]}";
          } else {
            _position = oPosition.toString().split('.')[0];
            _duration = oDuration.toString().split('.')[0];
          }
        });
      }
    }
    if (_polyvController.value.isCompleted) {
      _isBuffing = false;
      _polyvController.pause();
      resetVideoPlayer();
      if (widget.onEnded != null) {
        widget.onEnded!(_polyvController.value);
      }
      setState(() {});
    }

    if (_polyvController.value.hasError) {
      _hasPlayError = true;
      _initialized = false;
      if (_polyvController.value.position != Duration.zero) {
        _errorPosition = _polyvController.value.position;
      }
      setState(() {});
    }
  }

  /// 动态生成进度条组件
  List<Widget> _generateVideoProgressChildren() {
    Map<String, Widget> videoProgressWidgets = {
      'rewind': Padding(
          padding: const EdgeInsets.symmetric(horizontal: 2),
          child: GestureDetector(
            onTap: () {
              fastRewind();
            },
            child: videoStyle.videoControlBarStyle.rewindIcon,
          )),
      'play': Padding(
        padding: const EdgeInsets.symmetric(horizontal: 2),
        child: GestureDetector(
          onTap: () {
            togglePlay();
          },
          child: _polyvController.value.isPlaying
              ? videoStyle.videoControlBarStyle.pauseIcon
              : videoStyle.videoControlBarStyle.playIcon,
        ),
      ),
      'forward': Padding(
          padding: const EdgeInsets.symmetric(horizontal: 2),
          child: GestureDetector(
            onTap: () {
              fastForward();
            },
            child: videoStyle.videoControlBarStyle.forwardIcon,
          )),

      ///线条视频进度条
      'progress': Expanded(
        child: Container(
          padding: const EdgeInsets.symmetric(horizontal: 8),
          child: VideoLinearProgressBar(
            _polyvController,
            allowScrubbing: playOptions.allowScrubbing,
            onProgressDrag: (Duration position, Duration duration) {
              widget.onProgressDrag?.call(position, duration);
              _estimatedTimeNotifier.update(
                position: position,
                duration: duration,
              );
            },
            onDragEnd: () {
              _estimatedTimeNotifier.dragEnd();
            },
            onSeekTo: (Duration position) {
              seekTo(position);
            },
            padding: videoStyle.videoControlBarStyle.progressStyle.padding,
            progressStyle: videoStyle.videoControlBarStyle.progressStyle,
          ),
        ),
      ),

      'time': Padding(
        padding: videoStyle.videoControlBarStyle.timePadding,
        child: Text(
          "$_position / $_duration",
          style: videoStyle.videoControlBarStyle.timeTextStyle,
        ),
      ),
      'position-time': Padding(
        padding: videoStyle.videoControlBarStyle.timePadding,
        child: Text(
          _position,
          style: videoStyle.videoControlBarStyle.timeTextStyle,
        ),
      ),
      'duration-time': Padding(
        padding: videoStyle.videoControlBarStyle.timePadding,
        child: Text(
          _duration,
          style: videoStyle.videoControlBarStyle.timeTextStyle,
        ),
      ),
      'speed': Padding(
        padding: const EdgeInsets.symmetric(horizontal: 2),
        child: GestureDetector(
          onTap: toggleSpeedControls,
          child: Text(
            _speedTitle,
            style: videoStyle.videoSpeedButtonStyle.textStyle,
          ),
        ),
      ),
      'definition': playOptions.definitionList.isNotEmpty
          ? Padding(
              padding: const EdgeInsets.symmetric(horizontal: 2),
              child: GestureDetector(
                onTap: () {
                  if (_showMenu) {
                    toggleControls();
                  }
                  _definitionBarController?.forward();
                },
                child: Text(
                  _definitionTitle,
                  style: videoStyle.videoSpeedButtonStyle.textStyle,
                ),
              ),
            )
          : const SizedBox(),
      'fullscreen': Padding(
        padding: const EdgeInsets.symmetric(horizontal: 2),
        child: GestureDetector(
          onTap: toggleFullScreen,
          child: _fullScreened
              ? videoStyle.videoControlBarStyle.fullscreenExitIcon
              : videoStyle.videoControlBarStyle.fullscreenIcon,
        ),
      ),
    };

    List<Widget> videoProgressChildrens = [];
    var userSpecifyItem = videoStyle.videoControlBarStyle.itemList;

    for (var i = 0; i < userSpecifyItem.length; i++) {
      videoProgressChildrens.add(videoProgressWidgets[userSpecifyItem[i]]!);
    }

    return videoProgressChildrens;
  }

  /// 内置组件
  List<Widget> _videoBuiltInChildrens() {
    return [
      /// 顶部控制拦
      videoStyle.videoTopBarStyle.show
          ? VideoTopBar(
              animation: _controlTopBarAnimation,
              videoTopBarStyle: videoStyle.videoTopBarStyle,
              videoControlBarStyle: videoStyle.videoControlBarStyle,
              onPop: () {
                if (_fullScreened) {
                  toggleFullScreen();
                } else {
                  widget.onPop?.call(
                    const VideoPlayerValue(duration: Duration(seconds: 0)),
                  );
                }
              })
          : const Align(),

      /// 是否显示播放按钮
      videoStyle.showPlayIcon &&
              _initialized &&
              (!_polyvController.value.isPlaying && !_isEnded) &&
              !_isBuffing && !_hasPlayError
          ? Align(
              alignment: Alignment.center,
              child: GestureDetector(
                onTap: () {
                  if (!_polyvController.value.isPlaying) {
                    togglePlay();
                  }
                },
                child: videoStyle.playIcon,
              ),
            )
          : const SizedBox(),

      /// 是否显示重播按钮
      _initialized && _isEnded && videoStyle.showReplayIcon
          ? Align(
              alignment: Alignment.center,
              child: GestureDetector(
                onTap: replay,
                child: videoStyle.replayIcon,
              ),
            )
          : const SizedBox(),

      /// 重试按钮
      VideoRetryButton(
        hasError: _hasPlayError,
        errorMsg: '网络连接错误，检测网络后重试',
        onRetry: _retry,
      ),

      /// 底部控制拦
      VideoBottomBar(
        animation: _controlBottomBarAnimation,
        videoControlBarStyle: _videoControlBarStyle,
        children: _generateVideoProgressChildren(),
      ),

      /// 中间速度栏
      VideoSpeedBar(
        hidden: _hiddenSpeed,
        speedItemList: playOptions.speedList,
        style: videoStyle.videoSpeedItemStyle,
        selectedIndex: _selectedSpeedIndex,
        onTapItem: (int index) {
          _selectedSpeedIndex = index;
          VideoSpeedItem item = playOptions.speedList[index];
          _speedItem = item;
          _speedTitle = item.title;
          toggleSpeedControls();
          _polyvController.setPlaybackSpeed(item.speed);
          widget.onSpeedChange?.call(item);
        },
        onHidden: () {
          toggleSpeedControls();
        },
      ),

      /// 倍速提示
      VideoSpeedTip(
        hidden: _hiddenSpeedTip,
        videoSpeedTipStyle: videoStyle.videoSpeedTipStyle,
        speed: _speedTitle,
      ),

      /// 清晰度设置栏
      VideoDefinitionSideBar(
        itemList: playOptions.definitionList,
        videoDefinitionItemStyle: videoStyle.videoDefinitionItemStyle,
        onInit: (AnimationController definitionBarController) {
          _definitionBarController = definitionBarController;
        },
        onTapItem: (int index) {
          Duration position = _polyvController.value.position;
          VideoDefinitionItem item = playOptions.definitionList[index];
          _updateDataSource(
            type: item.sourceType,
            source: item.dataSource,
            initializeCallback: () {
              seekTo(position);
            },
          );
          _isBuffing = true;
          _definitionTitle = item.title;
          widget.onDefinitionChange?.call(item);
          setState(() {});
        },
      ),

      /// 预估时间栏
      VideoEstimatedTimeBar(
        notifier: _estimatedTimeNotifier,
        videoEstimatedTimeBarStyle: videoStyle.videoEstimatedTimeBarStyle,
      ),

      widget.brightnessWidget ??
          BrightnessWidget(
            brightness: _brightness,
            videoBrightnessStyle: videoStyle.videoBrightnessStyle,
          ),

      widget.volumeWidget ??
          VolumeWidget(
            volume: _volume,
            videoVolumeStyle: videoStyle.videoVolumeStyle,
          ),

      /// Loading
      (!_initialized || _isBuffing) && !_hasPlayError
          ? VideoLoadingView(loadingStyle: videoStyle.videoLoadingStyle)
          : const Align()
    ];
  }

  @override
  Widget build(BuildContext context) {
    /// Video children
    final videoChildrens = <Widget>[
      /// 视频区域
      GestureDetector(
        //点击
        onTap: () {
          //显示或隐藏菜单栏和进度条
          toggleControls();
        },
        //双击
        onDoubleTap: () {
          if (!_polyvController.value.isInitialized) return;
          togglePlay();
        },

        /// 水平滑动 - 调节视频进度
        onHorizontalDragStart: (DragStartDetails details) {
          if (!_polyvController.value.isInitialized) return;
          _draggingDuration = _polyvController.value.position;
        },
        onHorizontalDragUpdate: (DragUpdateDetails details) {
          if (!_polyvController.value.isInitialized) return;
          if (!_showMenu) {
            setState(() {
              _showMenu = true;
            });
            _createHideControlBarTimer();
          }
          if (details.primaryDelta != null) {
            if (details.primaryDelta! > 0) {
              /// 向右滑动
              int milliseconds = _draggingDuration.inMilliseconds +
                  playOptions.progressGestureUnit;
              milliseconds =
                  milliseconds > _polyvController.value.duration.inMilliseconds
                      ? _polyvController.value.duration.inMilliseconds
                      : milliseconds;
              _draggingDuration = Duration(milliseconds: milliseconds);
            } else {
              int milliseconds = _draggingDuration.inMilliseconds -
                  playOptions.progressGestureUnit;
              milliseconds = milliseconds < 0 ? 0 : milliseconds;
              _draggingDuration = Duration(milliseconds: milliseconds);
            }
            _estimatedTimeNotifier.update(
              position: _draggingDuration,
              duration: _polyvController.value.duration,
            );
          }
        },
        onHorizontalDragEnd: (DragEndDetails details) {
          _estimatedTimeNotifier.dragEnd();
          seekTo(_draggingDuration);
        },

        /// 垂直滑动 - 调节亮度以及音量
        onVerticalDragStart: (DragStartDetails details) {
          if (!_polyvController.value.isInitialized) return;
        },
        onVerticalDragUpdate: (DragUpdateDetails details) async {
          if (!_polyvController.value.isInitialized ||
              details.primaryDelta == null) {
            return;
          }
          // 右侧垂直滑动 - 音量调节
          if (details.globalPosition.dx >= (screenSize.width / 2)) {
            _volume.value = _polyvController.value.volume;
            if (details.primaryDelta! > 0) {
              //往下滑动
              _volume.value =
                  _polyvController.value.volume - playOptions.volumeGestureUnit;
              onVolume?.call(_volume.value);
              if (_volume.value <= 0) {
                _volume.value = 0.0;
              }
              onVolume?.call(_volume.value);
              _polyvController.setVolume(_volume.value);
            } else {
              //往上滑动
              _volume.value =
                  _polyvController.value.volume + playOptions.volumeGestureUnit;
              onVolume?.call(_volume.value);
              if (_volume.value >= 1) {
                _volume.value = 1.0;
              }
              onVolume?.call(_volume.value);
              _polyvController.setVolume(_volume.value);
            }
            _volume.value = _polyvController.value.volume;
          } else {
            if (_originBrightness == null) {
              await initBrightness();
            }
            // 左侧垂直滑动 - 亮度调节
            if (details.primaryDelta! > 0) {
              //往下滑动
              _brightness.value =
                  _brightness.value - playOptions.brightnessGestureUnit;
              onBrightness?.call(_brightness.value);
              if (_brightness.value <= 0) {
                _brightness.value = 0.0;
              }
              onBrightness?.call(_brightness.value);
              await _polyvController.setBrightness(_brightness.value);
            } else {
              //往上滑动
              _brightness.value =
                  _brightness.value + playOptions.brightnessGestureUnit;
              onBrightness?.call(_brightness.value);
              if (_brightness.value >= 1) {
                _brightness.value = 1.0;
              }
              onBrightness?.call(_brightness.value);
              await _polyvController.setBrightness(_brightness.value);
            }
          }
        },
        onVerticalDragEnd: (DragEndDetails details) {},

        /// 长按 2 倍速播放
        onLongPress: () {
          if (!_polyvController.value.isInitialized) return;
          VideoSpeedItem item = VideoSpeedItem(speed: 2.0, title: '2X');
          _polyvController.setPlaybackSpeed(item.speed);
          onSpeedChange?.call(item);
          _speedTitle = item.title;
          _hiddenSpeedTip = false;
          setState(() {});
        },

        /// 取消长按恢复之前选择的速度播放
        onLongPressUp: () {
          if (!_polyvController.value.isInitialized) return;
          _polyvController.setPlaybackSpeed(_speedItem.speed);
          onSpeedChange?.call(_speedItem);
          _speedTitle = _speedItem.title;
          _hiddenSpeedTip = true;
          setState(() {});
        },

        ///视频播放器
        child: DecoratedBox(
          decoration: const BoxDecoration(color: Colors.black),
          child: _renderPlayer(),
        ),
      ),

      ///控制拦以及(可拓展)元素
    ];

    /// 内置元素
    videoChildrens.addAll(_videoBuiltInChildrens());

    /// 自定义拓展元素
    videoChildrens.addAll(widget.children ?? []);

    /// 构建video
    return AspectRatio(
      aspectRatio: _fullScreened
          ? _calculateAspectRatio(context)
          : playOptions.aspectRatio,

      /// build 所有video组件
      child: Stack(children: videoChildrens),
    );
  }

  Widget _renderPlayer() {
    TargetPlatform targetPlatform = defaultTargetPlatform;
    switch (targetPlatform) {
      case TargetPlatform.android:
        return AndroidView(
          viewType: 'plugins.polyv/video',
          hitTestBehavior: PlatformViewHitTestBehavior.transparent,
          onPlatformViewCreated: (int viewID) {
            _viewID = viewID;
            _polyvController
              ..initialize(viewID: viewID).then((value) {
                _handleInit();
              })
              ..setLooping(playOptions.loop);
          },
          creationParamsCodec: const StandardMessageCodec(),
        );
      case TargetPlatform.iOS:
        return UiKitView(
          viewType: 'plugins.polyv/video',
          hitTestBehavior: PlatformViewHitTestBehavior.transparent,
          onPlatformViewCreated: (int viewID) {
            _viewID = viewID;
            _polyvController
              ..initialize(viewID: viewID).then((value) {
                _handleInit();
              })
              ..setLooping(playOptions.loop);
          },
          creationParamsCodec: const StandardMessageCodec(),
        );
      default:
        throw Exception('Unsupported platform view');
    }
  }

  void setVolume(double volume) {
    double vol = volume;
    if (vol <= 0.0) {
      vol = 0.0;
    }
    if (vol >= 1.0) {
      vol = 1.0;
    }
    if (_polyvController.value.isInitialized) {
      widget.onVolume?.call(vol);
      _polyvController.setVolume(vol);
    }
  }

  /// 计算设备的宽高比
  double _calculateAspectRatio(BuildContext context) {
    final width = screenSize.width;
    final height = screenSize.height;

    /// return widget.playOptions.aspectRatio ?? controller.value.aspectRatio;
    return width > height ? width / height : height / width;
  }

  /// 重试
  void _retry() {
    Duration position = _errorPosition;
    _hasPlayError = false;
    _updateDataSource(
      type: _sourceType,
      source: _dataSource,
      initializeCallback: () {
        seekTo(position);
      },
    );
  }

  /// 重播
  void replay() {
    _isEnded = false;
    _updateDataSource(
      source: _dataSource,
      type: _sourceType,
    );
  }

  /// 点击播放或暂停
  void togglePlay() {
    _createHideControlBarTimer();

    if (_polyvController.value.isPlaying) {
      _polyvController.pause();
      widget.onPause?.call(_polyvController.value);
    } else {
      _polyvController.play();
      widget.onPlay?.call(_polyvController.value);
    }
    setState(() {});
  }

  /// 显示或隐藏速度栏
  void toggleSpeedControls() {
    setState(() {
      _hiddenSpeed = !_hiddenSpeed;
    });
  }

  /// 显示或隐藏菜单栏
  void toggleControls() {
    _clearHideControlBarTimer();

    if (!_showMenu) {
      _showMenu = true;
      _createHideControlBarTimer();
    } else {
      _showMenu = false;
    }
    setState(() {
      if (_showMenu) {
        _controlBarAnimationController.forward();
      } else {
        _controlBarAnimationController.reverse();
      }
    });
  }

  void _createHideControlBarTimer() {
    _clearHideControlBarTimer();

    ///如果是播放状态5秒后自动隐藏
    _showTime = Timer(const Duration(milliseconds: 5000), () {
      if (_polyvController.value.isPlaying) {
        if (_showMenu && mounted) {
          setState(() {
            _showMenu = false;
            _controlBarAnimationController.reverse();
          });
        }
      }
    });
  }

  void _clearHideControlBarTimer() {
    _showTime?.cancel();
  }

  /// 视频快退
  void fastRewind() {
    _createHideControlBarTimer();

    setState(() {
      debugPrint(_polyvController.value.position.toString());
      var currentPosition = _polyvController.value.position;
      seekTo(Duration(
          seconds: currentPosition.inSeconds - playOptions.seekSeconds));
    });
  }

  /// 视频快进
  void fastForward() {
    _createHideControlBarTimer();

    setState(() {
      var currentPosition = _polyvController.value.position;
      seekTo(Duration(
          seconds: currentPosition.inSeconds + playOptions.seekSeconds));
    });
  }

  void _initPlayer() {
    if (dataSource == "") return;
    _dataSource = dataSource;
    _sourceType = sourceType;
    _polyvController = _createVideoPlayerController(
      source: dataSource,
      type: sourceType,
    )..addListener(_listener);
  }

  /// 创建video controller
  PolyvController _createVideoPlayerController({
    required DataSourceType type,
    required String source,
  }) {
    return PolyvController(
      dataSource: dataSource,
      sourceType: sourceType,
    );
  }

  /// 统一处理 seekTo
  void seekTo(Duration position) {
    if (_polyvController.value.isInitialized &&
        position < _polyvController.value.duration &&
        position >= Duration.zero) {
      _polyvController.seekTo(position);
    }
  }

  void _handleInit() {
    debugPrint("初始化完成");
    widget.onInit?.call(_polyvController);
    _initialized = true;
    setState(() {});
    if (playOptions.autoplay) {
      if (playOptions.startPosition.inSeconds != 0) {
        seekTo(playOptions.startPosition);
      }
      _polyvController.play();
      _isEnded = false;
    }
    _polyvController.setPlaybackSpeed(_speedItem.speed);
  }

  void _navigateLocally({
    required BuildContext context,
    bool fullScreen = false,
  }) async {
    ModalRoute? modalRoute = ModalRoute.of(context);
    if (!fullScreen) {
      if (modalRoute != null && modalRoute.willHandlePopInternally) {
        Navigator.of(context).pop();
      }
      return;
    } else {
      modalRoute?.addLocalHistoryEntry(LocalHistoryEntry(onRemove: () {
        if (_fullScreened) toggleFullScreen();
      }));
    }
  }
}
